package uk.ac.lkl.common.ui;



import java.awt.BorderLayout;
import java.awt.FlowLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.util.ArrayList;

import javax.swing.*;


/**
 * Wraps an editor with ok/cancel buttons.
 * 
 * @author Darren Pearce
 * @version $Revision$
 * @version $Date$
 * 
 */
public class ConfirmingEditor<O> extends JPanel {
	private static final long serialVersionUID = 1L;

    // so dialog can close
    // note: is fired regardless of whether ok or cancel is selected
    private ArrayList<ActionListener> actionListeners = new ArrayList<ActionListener>();

    /**
     * The editor that this instance wraps.
     * 
     */
    private Editor<O> editor;


    /**
     * Create a new instance wrapping the specified editor.
     * 
     * @param editor
     *            the editor to wrap
     */
    public ConfirmingEditor(
                            Editor<O> editor) {
        this.editor = editor;
        initialiseLayout();
    }


    /**
     * Initialise the layout.
     * 
     * Currently this places 'ok' and 'cancel' buttons underneath the
     * editor in a <code>BorderLayout</code>.
     * 
     * <p>
     * <b>Improvement:</b> Provide more flexibility in the location
     * of the ok/cancel buttons.
     * </p>
     * 
     * 
     */
    private void initialiseLayout() {
        setLayout(new BorderLayout());
        JButton cancelButton = new JButton("Cancel");
        JButton okButton = new JButton("Ok");

        okButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                updateData();
                fireActionPerformed(e);
            }
        });

        cancelButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                fireActionPerformed(e);
            }
        });

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(cancelButton);
        buttonPanel.add(okButton);
        add(buttonPanel, BorderLayout.SOUTH);
        add(editor, BorderLayout.CENTER);
    }


    /**
     * Use the data as specified in the editor to update the model.
     * 
     */
    protected void updateData() {
        editor.updateData();
    }


    /**
     * Set the model of this instance.
     * 
     * Data fields should be repainted as appropriate.
     * 
     * @param model
     *            the new model to use
     * 
     */
    public void setModel(O model) {
        editor.setModel(model);
    }


    /**
     * Add an action listener to this instance.
     * 
     * <p>
     * <b>Improvement:</b> Use Multicaster.
     * </p>
     * 
     * @param listener
     * 
     */
    public void addActionListener(ActionListener listener) {
        actionListeners.add(listener);
    }


    /**
     * Fire an action event.
     * 
     * <p>
     * <b>Note:</b> this event is fired regardless of whether ok or
     * cancel is pressed. It is simply an indication that a button has
     * been clicked.
     * </p>
     * 
     * @param e
     *            the event to fire
     * 
     */
    private void fireActionPerformed(ActionEvent e) {
        for (ActionListener listener : actionListeners)
            listener.actionPerformed(e);
    }

}
